﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using XML_VML.Object;

namespace XML_VML
{
    public class DesignerCanvas : Canvas
    {
        private Point? _dragStartPoint;
        private MainWindow _parent;

        public void DrawList(List<VObject> objects)
        {
            
        }

        public void SetParent(MainWindow pr)
        {
            _parent = pr;
        }

        public void DeselectAll()
        {
            
        }

        private void ReadGroup(VGroup group)
        {
            if(group != null)
            {
                foreach (var t in group.Elements)
                {
                    if (t is VShape)
                    {
                        var drShape = new DrawableShape();
                        var typename = ((VShape)t).Type;
                        VObject temp = null;
                        foreach (var z in _parent.root)
                        {
                            var vShapeType = z as VShapeType;
                            if (vShapeType == null) continue;
                            if (vShapeType.Id == typename)
                            {
                                temp = z;
                            }
                        }
                        drShape.SetData(t as VShape, temp as VShapeType);
                        Children.Add(drShape);
                    }
                    else if (t is VGroup)
                    {
                        ReadGroup(t as VGroup);
                    }
                    else if (t is VLine)
                    {
                        var drLine = new DrawableLine();
                        drLine.SetData(t as VLine);
                        Children.Add(drLine);
                    }
                    else if (t is VPolyLine)
                    {
                        var drPolyline = new DrawablePolyline();
                        drPolyline.SetData(t as VPolyLine);
                        Children.Add(drPolyline);
                    }
                    else if (t is VCurve)
                    {
                        var drCurve = new DrawableCurve();
                        drCurve.SetData(t as VCurve);
                        Children.Add(drCurve);
                    }
                    else if (t is VRect)
                    {
                        var drRect = new DrawableRect();
                        drRect.SetData(t as VRect);
                        Children.Add(drRect);
                    }
                    else if (t is VRoundRect)
                    {
                        var drRRect = new DrawableRoundRect();
                        drRRect.SetData(t as VRoundRect);
                        Children.Add(drRRect);
                    }
                    else if (t is VOval)
                    {
                        var drOval = new DrawableOval();
                        drOval.SetData(t as VOval);
                        Children.Add(drOval);
                    }
                    else if (t is VArc)
                    {
                        //not done yet
                    }
                    else if (t is VImage)
                    {
                        //not done yet
                    }
                    else if (t is VBackground)
                    {
                        //not done yet
                    }
                }
            }
        }

        public void DrawAll()
        {
            Children.Clear();
            foreach (var t in _parent.root)
            {
                if (t is VShape)
                {
                    var drShape = new DrawableShape();
                    var typename = ((VShape) t).Type;
                    VObject temp = null;
                    foreach (var z in _parent.root)
                    {
                        var vShapeType = z as VShapeType;
                        if (vShapeType == null) continue;
                        if(vShapeType.Id == typename)
                        {
                            temp = z;
                        }
                    }
                    drShape.SetData(t as VShape, temp as VShapeType);
                    Children.Add(drShape);
                }
                else if (t is VGroup)
                {
                    ReadGroup(t as VGroup);
                }
                else if (t is VLine)
                {
                    var drLine = new DrawableLine();
                    drLine.SetData(t as VLine);
                    Children.Add(drLine);
                }
                else if (t is VPolyLine)
                {
                    var drPolyline = new DrawablePolyline();
                    drPolyline.SetData(t as VPolyLine);
                    Children.Add(drPolyline);
                }
                else if (t is VCurve)
                {
                    var drCurve = new DrawableCurve();
                    drCurve.SetData(t as VCurve);
                    Children.Add(drCurve);
                }
                else if (t is VRect)
                {
                    var drRect = new DrawableRect();
                    drRect.SetData(t as VRect);
                    Children.Add(drRect);
                }
                else if (t is VRoundRect)
                {
                    var drRRect = new DrawableRoundRect();
                    drRRect.SetData(t as VRoundRect);
                    Children.Add(drRRect);
                }
                else if (t is VOval)
                {
                    var drOval = new DrawableOval();
                    drOval.SetData(t as VOval);
                    Children.Add(drOval);
                }
                else if (t is VArc)
                {
                    //not done yet
                }
                else if (t is VImage)
                {
                    //not done yet
                }
                else if (t is VBackground)
                {
                    //not done yet
                }
            }
        }

        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            base.OnMouseDown(e);
            if (!Equals(e.Source, this)) return;
            _dragStartPoint = e.GetPosition(this);
            DeselectAll();
            e.Handled = true;
        }

        protected override void OnDrop(DragEventArgs e)
        {
            base.OnDrop(e);
            var xamlString = e.Data.GetData("DESIGNER_ITEM") as string[];
            if (xamlString == null || String.IsNullOrEmpty(xamlString[0])) return;

            //var content = XamlReader.Load(XmlReader.Create(new StringReader(xamlString[1]))) as FrameworkElement;
            var content = xamlString[0];

            if (_parent.root == null)
            {
                _parent.root = new List<VObject>();
            }

            var position = e.GetPosition(this);
            int posx = Convert.ToInt32(Math.Round(position.X, 0, MidpointRounding.ToEven));
            int poxy = Convert.ToInt32(Math.Round(position.Y, 0, MidpointRounding.ToEven));

            switch (content.ToLower())
            {
                case "line":
                    var line = new VLine();
                    _parent.root.Add(line);
                    var drLine = new DrawableLine();
                    line.From = new Point(0, 0);
                    line.To = new Point(50, 50);
                    line.From = new Point(line.From.X + position.X, line.From.Y + position.Y);
                    line.To = new Point(line.To.X + position.X, line.To.Y + position.Y);
                    line.StrokeWeight = 2;
                    drLine.SetData(_parent.root[_parent.root.Count - 1] as VLine);
                    Children.Add(drLine);
                    break;
                case "polyline":
                    var polyline = new VPolyLine();
                    if(polyline.Points.Count == 0)
                    {
                        polyline.Points.Add(new Point(0 + posx, 0 + poxy));
                        polyline.Points.Add(new Point(25 + posx, 25 + poxy));
                        polyline.Points.Add(new Point(50 + posx, 0 + poxy));
                    }

                    _parent.root.Add(polyline);
                    var drPolyline = new DrawablePolyline();
                    polyline.StrokeWeight = 2;
                    drPolyline.SetData(_parent.root[_parent.root.Count - 1] as VPolyLine);
                    Children.Add(drPolyline);
                    break;
                case "curve":
                    var curve = new VCurve();
                    _parent.root.Add(curve);
                    var drCurve = new DrawableCurve();
                    curve.From = new Point(curve.From.X + position.X, curve.From.Y + position.Y);
                    curve.To = new Point(curve.To.X + position.X, curve.To.Y + position.Y);
                    curve.Control1 = new Point(curve.Control1.X + position.X, curve.Control1.Y + position.Y);
                    curve.Control2 = new Point(curve.Control2.X + position.X, curve.Control2.Y + position.Y);
                    curve.StrokeWeight = 2;
                    drCurve.SetData(_parent.root[_parent.root.Count-1] as VCurve);
                    Children.Add(drCurve);
                    break;
                case "rect":
                    var rect = new VRect();
                    _parent.root.Add(rect);
                    var drRect = new DrawableRect();
                    var initStyle = new VStyle {Width = 100, Height = 100};
                    initStyle.Left = position.X - initStyle.Width/2;
                    initStyle.Top = position.Y - initStyle.Height/2;
                    rect.Style = FileManager.GetStringFromStyle(initStyle);
                    drRect.SetData(_parent.root[_parent.root.Count - 1] as VRect);
                    Children.Add(drRect);
                    break;
                case "roundrect":
                    var roundrect = new VRoundRect();
                    _parent.root.Add(roundrect);
                    var drRRect = new DrawableRoundRect();
                    var initRRStyle = new VStyle {Width = 100, Height = 100};
                    initRRStyle.Left = position.X - initRRStyle.Width / 2;
                    initRRStyle.Top = position.Y - initRRStyle.Height / 2;
                    roundrect.Style = FileManager.GetStringFromStyle(initRRStyle);
                    drRRect.SetData(_parent.root[_parent.root.Count - 1] as VRoundRect);
                    Children.Add(drRRect);
                    break;
                case "oval":
                    var oval = new VOval();
                    _parent.root.Add(oval);
                    var drOval = new DrawableOval();
                    var initOvStyle = new VStyle {Width = 100, Height = 100};
                    initOvStyle.Left = position.X - initOvStyle.Width / 2;
                    initOvStyle.Top = position.Y - initOvStyle.Height / 2;
                    oval.Style = FileManager.GetStringFromStyle(initOvStyle);
                    drOval.SetData(_parent.root[_parent.root.Count - 1] as VOval);
                    Children.Add(drOval);
                    break;
                case "shape":
                    var shape = new VShape();
                    _parent.root.Add(shape);
                    var drShape = new DrawableShape();
                    var initShStyle = new VStyle {Width = 100, Height = 100};
                    initShStyle.Left = position.X - initShStyle.Width / 2;
                    initShStyle.Top = position.Y - initShStyle.Height / 2;
                    shape.Style = FileManager.GetStringFromStyle(initShStyle);
                    drShape.SetData(_parent.root[_parent.root.Count - 1] as VShape, null);
                    Children.Add(drShape);
                    break;
            }

            e.Handled = true;
        }

        

        protected override Size MeasureOverride(Size constraint)
        {
            var size = new Size();
            foreach (UIElement element in Children)
            {
                var left = GetLeft(element);
                var top = GetTop(element);
                left = double.IsNaN(left) ? 0 : left;
                top = double.IsNaN(top) ? 0 : top;

                element.Measure(constraint);

                var desiredSize = element.DesiredSize;
                if (double.IsNaN(desiredSize.Width) || double.IsNaN(desiredSize.Height)) continue;
                size.Width = Math.Max(size.Width, left + desiredSize.Width);
                size.Height = Math.Max(size.Height, top + desiredSize.Height);
            }

            // add some extra margin
            size.Width += 10;
            size.Height += 10;
            return size;
        }
    }
}
